// Fill out your copyright notice in the Description page of Project Settings.

#include "TapDBJNI.h"
#include "Android/AndroidJNI.h"
#include "Android/AndroidApplication.h"
#include "Android/AndroidJava.h"

#define TAPDB_CLASS_NAME "com/tapdb/sdk/TapDB"

#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "TapDB"

namespace TapDB {
    extern "C"
    {
        void jni_setUser(const char *userId)
        {
            JNIEnv* env = FAndroidApplication::GetJavaEnv();
            jclass jClass = FAndroidApplication::FindJavaClass(TAPDB_CLASS_NAME);
            const char* strMethod = "setUser";

            if(jClass)
            {
                jmethodID jMethod = env->GetStaticMethodID(jClass, strMethod, "(Ljava/lang/String;)V");

                if(jMethod)
                {
                    jstring j_string = env->NewStringUTF(userId);
                    env->CallStaticVoidMethod(jClass, jMethod, j_string);
                    env->DeleteLocalRef(j_string);
                }
                else
                {
                    __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find method %s ***", strMethod);
                }

                env->DeleteLocalRef(jClass);
            }
            else
            {
                __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find class %s ***", TAPDB_CLASS_NAME);
            }
        }

        void jni_setName(const char *name)
        {
            JNIEnv* env = FAndroidApplication::GetJavaEnv();
            jclass jClass = FAndroidApplication::FindJavaClass(TAPDB_CLASS_NAME);
            const char* strMethod = "setName";

            if(jClass)
            {
                jmethodID jMethod = env->GetStaticMethodID(jClass, strMethod, "(Ljava/lang/String;)V");

                if(jMethod)
                {
                    jstring j_string = env->NewStringUTF(name);
                    env->CallStaticVoidMethod(jClass, jMethod, j_string);
                    env->DeleteLocalRef(j_string);
                }
                else
                {
                    __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find method %s ***", strMethod);
                }

                env->DeleteLocalRef(jClass);
            }
            else
            {
                __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find class %s ***", TAPDB_CLASS_NAME);
            }
        }

        void jni_setLevel(int level)
        {
            JNIEnv* env = FAndroidApplication::GetJavaEnv();
            jclass jClass = FAndroidApplication::FindJavaClass(TAPDB_CLASS_NAME);
            const char* strMethod = "setLevel";

            if(jClass)
            {
                jmethodID jMethod = env->GetStaticMethodID(jClass, strMethod, "(I)V");

                if(jMethod)
                {
                    env->CallStaticVoidMethod(jClass, jMethod, level);
                }
                else
                {
                    __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find method %s ***", strMethod);
                }

                env->DeleteLocalRef(jClass);
            }
            else
            {
                __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find class %s ***", TAPDB_CLASS_NAME);
            }
        }

        void jni_setServer(const char *server)
        {
            JNIEnv* env = FAndroidApplication::GetJavaEnv();
            jclass jClass = FAndroidApplication::FindJavaClass(TAPDB_CLASS_NAME);
            const char* strMethod = "setServer";

            if(jClass)
            {
                jmethodID jMethod = env->GetStaticMethodID(jClass, strMethod, "(Ljava/lang/String;)V");

                if(jMethod)
                {
                    jstring j_string = env->NewStringUTF(server);
                    env->CallStaticVoidMethod(jClass, jMethod, j_string);
                    env->DeleteLocalRef(j_string);
                }
                else
                {
                    __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find method %s ***", strMethod);
                }

                env->DeleteLocalRef(jClass);
            }
            else
            {
                __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find class %s ***", TAPDB_CLASS_NAME);
            }
        }

        void jni_onCharge(const char *orderId, const char *product, int64_t amount, const char * currencyType, const char *payment)
        {
            JNIEnv* env = FAndroidApplication::GetJavaEnv();
            jclass jClass = FAndroidApplication::FindJavaClass(TAPDB_CLASS_NAME);
            const char* strMethod = "onCharge";

            if(jClass)
            {
                jmethodID jMethod = env->GetStaticMethodID(jClass, strMethod, "(Ljava/lang/String;Ljava/lang/String;JLjava/lang/String;Ljava/lang/String;)V");

                if(jMethod)
                {
                    jstring j_orderId = env->NewStringUTF(orderId);
                    jstring j_product = env->NewStringUTF(product);
                    jstring j_currencyType = env->NewStringUTF(currencyType);
                    jstring j_payment = env->NewStringUTF(payment);
                    env->CallStaticVoidMethod(jClass, jMethod, j_orderId, j_product, amount, j_currencyType, j_payment);
                    env->DeleteLocalRef(j_orderId);
                    env->DeleteLocalRef(j_product);
                    env->DeleteLocalRef(j_currencyType);
                    env->DeleteLocalRef(j_payment);
                }
                else
                {
                    __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find method %s ***", strMethod);
                }

                env->DeleteLocalRef(jClass);
            }
            else
            {
                __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find class %s ***", TAPDB_CLASS_NAME);
            }
        }

#define LOCALE_CLASS_NAME "java/util/Locale"

        static jobject GetJSONLocale(JNIEnv* env)
        {
            jobject j_jsonLocale = nullptr;
            jclass jClass = FAndroidApplication::FindJavaClass(LOCALE_CLASS_NAME);
            const char* strMethod = "getDefault";
            
            if (jClass)
            {                
                jmethodID jMethod = env->GetStaticMethodID(jClass, strMethod, "()Ljava/util/Locale;");

                if (jMethod)
                {
                    j_jsonLocale = env->CallStaticObjectMethod(jClass, jMethod);
                }
                else
                {
                    __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find method %s ***", strMethod);
                }

                env->DeleteLocalRef(jClass);
            }
            else
            {
                __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find class %s ***", LOCALE_CLASS_NAME);
            }
            return j_jsonLocale;
        }

#define GAMEACTIVITY_CLASS_NAME "com/epicgames/ue4/GameActivity"

        void jni_onEvent(const char *eventCode, const char *properties)
        {
            JNIEnv* env = FAndroidApplication::GetJavaEnv();
            jclass jClass = FAndroidApplication::FindJavaClass(GAMEACTIVITY_CLASS_NAME);           
            const char* strMethod = "onTapDBEvent";

            if(jClass)
            {
                jmethodID jMethod = env->GetStaticMethodID(jClass, strMethod, "(Ljava/lang/String;Ljava/lang/String;)V");

                if(jMethod)
                {
                    jstring j_eventCode = env->NewStringUTF(eventCode);
                    jstring j_properties = env->NewStringUTF(properties);
                    env->CallStaticVoidMethod(jClass, jMethod, j_eventCode, j_properties);
                    env->DeleteLocalRef(j_eventCode);
                    env->DeleteLocalRef(j_properties);
                }
                else
                {
                    __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find method %s ***", strMethod);
                }

                env->DeleteLocalRef(jClass);
            }
            else
            {
                __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "*** Failed to find class %s ***", GAMEACTIVITY_CLASS_NAME);
            }
            
        }
    }
}